
//
// 110621 - AH - (Zen *) Created.
// 110622 - AH - (Fotballpuben *) Finished implementation regarding writing of
//               visitor input.
// 110626 - AH - Finished implementation regarding writing of retrieved data.
// 110629 - AH - (Bybanen *) Extracted XmlContentGenerator implemented as an
//               inner class, did become ExchangeXmlContentGenerator.
// 110907 - AH - Fixed that top element was not written!
// 120128 - AH - (Garage *) Support for new ontology ProductTable.
//

package org.soekrat.engine.io.responsexml;

import static org.soekrat.engine.io.IOUtil.encode;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.soekrat.AttributeObject;
import org.soekrat.engine.Soekrat2Engine;
import org.soekrat.engine.forest.Tree;
import org.soekrat.engine.io.xmlutil.XmlGenerator;
import org.soekrat.engine.io.xmlutil.XmlTopContentGenerator;
import org.soekrat.engine.network.Cluster;
import org.soekrat.engine.network.NetworkNode;
import org.soekrat.engine.ontology.ptable.Product;
import org.soekrat.engine.pit.Content;
import org.soekrat.engine.pit.Node;
import org.soekrat.engine.pit.Pit;
import org.soekrat.engine.rethor.RethorUtil;

/**
 * <p>
 *   Factory method for creating 
 *   {@link XmlGenerator} for saving chat.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class SaveChatXmlGeneratorFactory 
{
  // Private constructor since never instantiated: Only static factory method
  // found here.
  private SaveChatXmlGeneratorFactory(){}
  
  private static final XmlTopContentGenerator c_top=
    new XmlTopContentGenerator("soekrat-chat")
  {
    // Specified in XmlTopContentGenerator.
    public String getStart() 
    {
      Date date=new Date();
      
      CharArrayWriter caw=new CharArrayWriter();
      PrintWriter pw=new PrintWriter(caw);
      
      StringBuilder sb=new StringBuilder();
      sb.append("<").append(getTopElement()).append(" time='").append(date)
        .append("'>");
      pw.append(sb.toString());
      
      pw.flush();
      return caw.toString();
    }
      
  };
  
  /**
   * <p>
   *   Gets
   *   {@link XmlGenerator} instance to use for saving chat.
   * </p>
   * @return Instance.
   */
  public static XmlGenerator getInstance(Soekrat2Engine engine)
  {
    if (engine==null)
    {
      throw new NullPointerException("engine");
    }
    
    XmlGenerator retVal=new XmlGenerator();
    retVal.setXmlTopContentGenerator(c_top);
    retVal.setXmlContentGenerator(new ExchangeXmlContentGenerator(engine));
    return retVal;
  }
  
  static void writeWheelXml(List<AttributeObject> l, PrintWriter pw, 
    Pit pit)
  {
    List<AttributeObject> resources=new ArrayList<AttributeObject>();
    List<AttributeObject> trees=new ArrayList<AttributeObject>();
    List<AttributeObject> clusters=new ArrayList<AttributeObject>();
    List<AttributeObject> products=new ArrayList<AttributeObject>();
    
    RethorUtil.centrifuge(l, resources, trees, clusters, products);
    
    pw.println();
    pw.println("<retrieved>");
    
    writeMineRetrievedXml(resources, pw, pit);
    writeForestRetrievedXml(trees, pw, pit);
    writeClustersXml(clusters, pw, pit);
    writeProductsXml(products, pw, pit);
    
    pw.println();
    pw.println("</retrieved>");
  }
  
  static void writeSpareWheelXml(List<AttributeObject> l, 
    PrintWriter pw)
  {
    pw.println();
    pw.println("<rethor>");
    for (AttributeObject curr : l)
    {
      String txt=curr.getName();
      txt=(txt==null) ? "" : txt.trim();
      if (txt.length()>0)
      {
        pw.println();
        pw.println("  <item>");
        pw.println(encode(txt));
        pw.println("  </item>");  
      }
    }
    pw.println("  </rethor>");
  }
  
  private static void writeMineRetrievedXml(List<AttributeObject> resources, 
    PrintWriter pw, Pit pit)
  {
    if (resources.isEmpty()) return;
    
    pw.println();
    pw.println();
    pw.println("<ontology name='mine'>");
    
    for (AttributeObject curr : resources) 
    {
      pw.println("  <resource>");

      String name=curr.getName();
      
      pw.print("    <name>");
      pw.print(encode(name));
      pw.println("</name>");
      
      writeContent(pit, "mine", name, pw, "    ");
      
      pw.println("  </resource>");
    }
    
    pw.println("</ontology>");
    pw.println();
    pw.println();
  }
  
  private static void writeProductsXml(List<AttributeObject> products, 
    PrintWriter pw, Pit pit)
  {
    if (products.isEmpty()) return;
      
    pw.println();
    pw.println();
    pw.println("<ontology name='product-table'>");
      
    for (AttributeObject curr : products) 
    {
      pw.println("  <product>");

      Product prod=(Product)curr;
      String name=prod.toString();
        
      pw.print("    <name>");
      pw.print(encode(name));
      pw.println("</name>");
        
      writeContent(pit, "product-table", name, pw, "    ");
        
      pw.println("  </product>");
    }
      
    pw.println("</ontology>");
    pw.println();
    pw.println();
  }
  
  private static void writeForestRetrievedXml(List<AttributeObject> trees, 
    PrintWriter pw, Pit pit)
  {
    if (trees.isEmpty()) return;
    
    Tree tree=RethorUtil.buildRetrievedTree(trees);
    
    pw.println();
    pw.println();
    pw.println("<ontology name='forest'>");
    
    writeRetrievedTreeXml(tree, pw, pit, "  ");
    
    pw.println("</ontology>");
    pw.println();
    pw.println();
  }
  
  private static void writeRetrievedTreeXml(Tree tree, PrintWriter pw, Pit pit,
    String ident)
  {
    pw.println(ident+"<tree>");
    
    pw.print(ident+"  <name>");
    
    String name=tree.getName();
    
    pw.print(encode(name));
    
    pw.println("</name>");
    
    writeContent(pit, "forest", name, pw, ident);
    
    int n=tree.getChildCount();
    for (int i=0; i<n; i++)
    {
      Tree child=tree.getChild(i);
      writeRetrievedTreeXml(child, pw, pit, ident+"  ");
    }
    
    pw.println(ident+"</tree>");
  }
  
  private static void writeClustersXml(List<AttributeObject> clusters, 
    PrintWriter pw, Pit pit)
  {
    if (clusters.isEmpty()) return;
    
    pw.println();
    pw.println();
    pw.println("<ontology name='network'>");
    
    for (AttributeObject c : clusters)
    {
      if (c instanceof Cluster)
      {
        Cluster cluster=(Cluster)c;  
      
        pw.println("  <cluster>");

        pw.println("    <nodes>");
        
        for (NetworkNode node : cluster)
        {
          String name=node.getName();
        
          pw.print("      <name>");
          pw.print(encode(name));
          pw.println("</name>");
        
          writeContent(pit, "network", name, pw, "      ");
        }
        
        pw.println("    </nodes>");
        
        pw.println("  </cluster>");
      }
    }
    pw.println("</ontology>");
  }
  
  private static void writeContent(Pit pit, String ontology, String name,
    PrintWriter pw, String ident)
  { 
    if (pit.hasContent(name, ontology))
    {
      Node node=pit.getNode(name);
      Content[] content=node.getContent(ontology);
      for (Content currc : content) 
      {
        pw.println(ident+"<content>");
        
        pw.println(encode(currc.getText()));
        
        pw.println(ident+"</content>");
      }
    }
  }
  
}
